package org.lql.chaos.mq.rabbitmq.consumer;

import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.lql.chaos.mq.rabbitmq.config.BusinessRetryConfig;
import org.lql.chaos.mq.rabbitmq.constant.RabbitMQConstant;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * @author: liangqinglong
 * @date: 2025-08-09 11:07
 * @description:
 **/
@Slf4j
@Component
public class BusinessRetryConsumer {

	@Autowired
	@Qualifier("rabbitTemplate")
	private RabbitTemplate rabbitTemplate;

	@RabbitListener(queues = RabbitMQConstant.BUSINESS_QUEUE, ackMode = "MANUAL")
	public void onMessage(String context, Message message, Channel channel) throws IOException {
		long deliveryTag = message.getMessageProperties().getDeliveryTag();
		try {
			log.info("[BUSINESS_QUEUE::{}] 尝试处理消息：{}", message.getMessageProperties().getConsumerTag(), context);
			// 模拟业务处理失败
			if (deliveryTag % 2 == 0) {
				throw new RuntimeException("模拟业务处理失败");
			}
			// 成功确认
			channel.basicAck(deliveryTag, false);
		} catch (Exception e) {
			log.error("[BUSINESS_QUEUE] 确认消息失败：{}", e.getMessage());
			Integer retryCount = (Integer) message.getMessageProperties()
					.getHeaders()
					.getOrDefault(BusinessRetryConfig.HDR_RETRY_COUNT, 0);
			int next = retryCount + 1;
			// 本次消费的消息先拒绝（不 requeue，避免死循环）
			channel.basicNack(deliveryTag, false, false);
			if (BusinessRetryConfig.hasMoreRetry(retryCount)) {
				// 2.1 还有重试机会：投到相应的延迟队列
				MessagePostProcessor mpp = msg -> {
					msg.getMessageProperties().getHeaders().put(BusinessRetryConfig.HDR_RETRY_COUNT, next);
					return msg;
				};
				String retryRoutingKey = BusinessRetryConfig.nextRetryRoutingKey(next);
				rabbitTemplate.convertAndSend(
						RabbitMQConstant.BUSINESS_RETRY_EXCHANGE,
						retryRoutingKey,
						message,
						mpp
				);
			} else {
				// 2.2 没有重试机会：直接丢弃、记录日志
				log.info("[BUSINESS_QUEUE] 没有重试机会，直接丢弃消息：{}", context);
				channel.basicReject(deliveryTag, false);
			}
		}
	}
}
